#ifndef TINYNDARRAY_NDARRAY_VIEW_H
#define TINYNDARRAY_NDARRAY_VIEW_H

namespace tinyndarray {
class NdArray;
class Substance;
class ElementProxy;
class ConstElementProxy;

size_t calculate_offset(const Index& index, const Shape& shape, const std::vector<size_t>& strides);

class NdArrayView {
public:
    NdArrayView(std::shared_ptr<Substance> substance, size_t offset, const Shape& shape,
                const std::vector<size_t>& strides)
        : m_substance(substance), m_offset(offset), m_shape(shape), m_strides(strides) {}

    // 切片操作（返回新视图）
    NdArrayView slice(const SliceIndex& slice_index) const;

    template <typename... I>
    NdArrayView slice(std::initializer_list<I>... slice_index) const;

    NdArrayView operator()(const SliceIndex& slice_index) const;

    template <typename... I>
    NdArrayView operator()(std::initializer_list<I>... slice_index) const;
    // 转换为拥有数据的NdArray（触发拷贝）
    NdArray to_ndarray() const;

    // 访问元素
    ElementProxy operator[](size_t index);

    // 一维索引（const）
    ConstElementProxy operator[](size_t index) const;

    // 多维索引（非const）
    ElementProxy operator[](const Index& index);
    // 多维索引（const）
    ConstElementProxy operator[](const Index& index) const;

    // 辅助方法：将一维索引转换为多维索引
    Index flat_index_to_multi(size_t index) const;

    // 属性访问
    const Shape& shape() const {
        return m_shape;
    }
    size_t offset() const {
        return m_offset;
    }
    const std::vector<size_t>& strides() const {
        return m_strides;
    }
    Dtype dtype() const;

    size_t size() const;

    bool is_contiguous() const;

    // 从 NdArray 赋值
    NdArrayView& operator=(const NdArray& src);

    // 从另一个 NdArrayView 赋值
    NdArrayView& operator=(const NdArrayView& src);

    // 通用赋值实现
    template <typename Source>
    NdArrayView& assign_from(const Source& src);

private:
    // 获取源数据的基指针
    template <typename Source>
    const char* get_source_base(const Source& src) const;

    // 计算源数据中的偏移
    template <typename Source>
    size_t calculate_source_offset(const Source& src, const std::vector<size_t>& indices) const;

    std::shared_ptr<Substance> m_substance;
    size_t m_offset;  // 字节偏移量
    Shape m_shape;
    std::vector<size_t> m_strides;  // 每个维度的字节步长
};

std::ostream& operator<<(std::ostream& os, const NdArrayView& arr);

NdArray operator+(const NdArrayView& lhs, const NdArray& rhs);
NdArray operator+(const NdArray& lhs, const NdArrayView& rhs);
NdArray operator+(const NdArrayView& lhs, const NdArrayView& rhs);
NdArray operator+(const NdArrayView& lhs, const float& rhs);
}  // namespace tinyndarray
#endif